package org.amos.filestorage.platform.s3;

import cn.hutool.core.util.StrUtil;
import com.google.common.base.Throwables;
import io.minio.*;
import io.minio.errors.*;
import org.amos.filestorage.exception.FileStorageException;
import org.amos.filestorage.platform.AbstractFilePlatform;
import org.amos.filestorage.platform.config.s3.MinIOFilePlatformConfig;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.function.Consumer;

/**
 * MinIO 存储
 */
public class MinIOFilePlatform extends AbstractFilePlatform<MinIOFilePlatformConfig> {

    private MinioClient client;

    public MinIOFilePlatform(String id, MinIOFilePlatformConfig config) {
        super(id, config);
    }

    @Override
    public void initClient() {
        client = new MinioClient.Builder()
                .credentials(config.getAccessKey(), config.getSecretKey())
                .endpoint(config.getEndPoint())
                .build();
    }

    @Override
    public String upload(byte[] bytes, String path, String type) {
        try {
            client.putObject(PutObjectArgs.builder().bucket(config.getBucket()).object(path)
                    .stream(new ByteArrayInputStream(bytes), bytes.length, -1)
                    .contentType(type).build());
            return StrUtil.format("{}/{}/{}", config.getEndPoint(), config.getBucket(), path);
        } catch (ErrorResponseException | InsufficientDataException | InternalException | ServerException |
                 InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException |
                 XmlParserException e) {

            throw new FileStorageException(Throwables.getStackTraceAsString(e));
        }
    }

    @Override
    public Boolean delete(String path) {
        try {
            client.removeObject(RemoveObjectArgs.builder().bucket(config.getBucket()).object(path).build());
            return Boolean.TRUE;
        } catch (ErrorResponseException | InsufficientDataException | InternalException | ServerException |
                 InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException |
                 XmlParserException e) {
            throw new FileStorageException(Throwables.getStackTraceAsString(e));
        }
    }


    @Override
    public Boolean exists(String path) {
        try {
            StatObjectResponse stat = client.statObject(StatObjectArgs.builder().bucket(config.getBucket()).object(path).build());
            return stat != null && stat.lastModified() != null;
        } catch (ErrorResponseException e) {
            String code = e.errorResponse().code();
            if ("NoSuchKey".equals(code)) {
                return Boolean.FALSE;
            }
            throw new FileStorageException("查询文件是否存在失败！", e);
        } catch (InsufficientDataException | InternalException | ServerException | InvalidKeyException |
                 InvalidResponseException | IOException | NoSuchAlgorithmException | XmlParserException e) {
            throw new FileStorageException("查询文件是否存在失败！", e);
        }
    }

    @Override
    public void download(String path, Consumer<InputStream> consumer) {
        try (InputStream in = client.getObject(GetObjectArgs.builder().bucket(config.getBucket()).object(path).build())) {
            consumer.accept(in);
        } catch (ErrorResponseException | InsufficientDataException | InternalException | ServerException |
                 InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException |
                 XmlParserException e) {
            throw new FileStorageException(Throwables.getStackTraceAsString(e));
        }
    }
}
